home *** CD-ROM | disk | FTP | other *** search
- From: island!argv@sun.com (Dan Heller)
- Subject: Mail User's Shell, version 6.0
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 10 (of 14)."
- # Contents: hdrs.c
- # Wrapped by rsalz@fig.bbn.com on Wed Apr 13 20:04:53 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'hdrs.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'hdrs.c'\"
- else
- echo shar: Extracting \"'hdrs.c'\" \(30675 characters\)
- sed "s/^X//" >'hdrs.c' <<'END_OF_FILE'
- X/* hdrs.c (c) copyright 1986 (Dan Heller) */
- X
- X/* Routines that deal with message headers inside messages */
- X#include "mush.h"
- X
- X/*
- X * get which message via the offset and search for the headers which
- X * match the string "str". there may be more than one of a field (like Cc:)
- X * so get them all and "cat" them together into the static buffer
- X * "buf" and return its address.
- X */
- char *
- header_field(n, str)
- char *str;
- X{
- X static char buf[BUFSIZ];
- X char tmp[BUFSIZ];
- X register char *p, *p2, *b = buf;
- X int contd_hdr; /* true if next line is a continuation of the hdr we want */
- X
- X if (fseek(tmpf, msg[n].m_offset, L_SET) == -1) {
- X error("fseek in %s (msg %d, folder=%s)", tempfile, n+1, mailfile);
- X turnon(glob_flags, READ_ONLY);
- X return NULL;
- X }
- X *b = 0;
- X while((p = fgets(tmp, sizeof(buf), tmpf)) && *p != '\n') {
- X if (*p != ' ' && *p != '\t') {
- X contd_hdr = 0;
- X /* strcmp ignoring case */
- X for(p2 = str; *p && *p2 && *p2 == lower(*p); ++p, ++p2);
- X /* MATCH is true if p2 is at the end of str and *p is ':' */
- X if (*p2 || *p++ != ':')
- X continue;
- X else
- X contd_hdr = 1;
- X } else if (!contd_hdr)
- X continue;
- X skipspaces(0);
- X p2 = no_newln(p);
- X *++p2 = ' ', *++p2 = 0;
- X if (strlen(p) + (b-buf) < sizeof (buf))
- X b += Strcpy(b, p);
- X }
- X if (b > buf) /* now get rid of the trailing blank */
- X *--b = 0;
- X return (*buf)? buf: NULL;
- X}
- X
- do_hdrs(argc, argv, list)
- register char **argv, list[];
- X{
- X register int pageful = 0, fnd;
- X int (*oldint)(), (*oldquit)(), show_deleted;
- X static int cnt;
- X register char *p;
- X char first_char = (argc) ? **argv: 'h';
- X
- X if (argc > 1 && !strcmp(argv[1], "-?"))
- X return help(0, "headers", cmd_help);
- X
- X if (!msg_cnt) {
- X if (ison(glob_flags, DO_PIPE))
- X return 0;
- X#ifdef CURSES
- X if (iscurses)
- X clear();
- X#endif /* CURSES */
- X#ifdef SUNTOOL
- X if (istool)
- X mail_status(0);
- X#endif /* SUNTOOL */
- X return 0;
- X }
- X if (first_char == ':' || (argc > 1 && argv[1][0] == ':')) {
- X if (first_char != ':')
- X argv++;
- X return specl_hdrs(argv, list);
- X }
- X
- X on_intr();
- X
- X if (argc && (argv[0][1] == '+' || argc > 1 && !strcmp(argv[1], "+")) ||
- X first_char == 'z' && !argv[1])
- X if (msg_cnt > screen)
- X cnt = min(msg_cnt - screen, n_array[0] + screen);
- X else
- X cnt = 0;
- X else if (argc && (argv[0][1] == '-' || argc > 1 && !strcmp(argv[1], "-")))
- X cnt = max((cnt - 2*screen), 0);
- X else if (argc && *++argv &&
- X (isdigit(**argv) || **argv == '^' || **argv == '$' || **argv == '.')
- X || ison(glob_flags, IS_PIPE)) {
- X /* if we're coming from a pipe, start display at the first msg bit
- X * set in the msg_list
- X */
- X if (ison(glob_flags, IS_PIPE)) {
- X if (isoff(glob_flags, DO_PIPE))
- X for (fnd = 0; fnd < msg_cnt; fnd++)
- X if (msg_bit(list, fnd))
- X wprint("%s\n", compose_hdr(fnd));
- X off_intr();
- X return 0;
- X }
- X /* if a number was given, use it */
- X if (!(fnd = chk_msg(*argv))) {
- X off_intr();
- X return -1;
- X }
- X for (cnt = fnd - 1; cnt > 0 && cnt + screen > msg_cnt; cnt--);
- X } else if (current_msg < n_array[0] || current_msg > n_array[screen-1])
- X cnt = current_msg; /* adjust if user reads passed screen bounds */
- X else if (cnt >= msg_cnt || !argc || !*argv)
- X cnt = max((cnt - screen), 0); /* adjust window to maintian position */
- X
- X show_deleted = !!do_set(set_options, "show_deleted");
- X
- X for (;pageful<screen && cnt<msg_cnt && isoff(glob_flags, WAS_INTR); cnt++) {
- X if (!iscurses && !show_deleted && first_char == 'h'
- X && ison(msg[cnt].m_flags, DELETE))
- X continue;
- X n_array[pageful++] = cnt;
- X /* this message was displayed -- set the bit */
- X if (list)
- X set_msg_bit(list, cnt);
- X /* if do_pipe, don't output anything */
- X if (ison(glob_flags, DO_PIPE))
- X continue;
- X p = compose_hdr(cnt);
- X if (!istool && (!iscurses || ison(glob_flags, IS_GETTING)))
- X puts(p);
- X#ifdef SUNTOOL
- X else if (istool) {
- X if (cnt == current_msg) /* embolden or reverse_video */
- X highlight(hdr_win, 0,pageful*l_height(DEFAULT), DEFAULT,p);
- X else
- X pw_text(hdr_win, 0, pageful * l_height(DEFAULT), PIX_SRC,
- X fonts[DEFAULT], p);
- X Clrtoeol(hdr_win, strlen(p)*l_width(DEFAULT),
- X pageful*l_height(DEFAULT), DEFAULT);
- X }
- X#endif /* SUNTOOL */
- X#ifdef CURSES
- X else if (iscurses)
- X mvprintw(pageful, 0, "%-.*s", COLS-2, p), clrtoeol();
- X#endif /* CURSES */
- X }
- X /* just in case a signal stopped us */
- X off_intr();
- X pageful++;
- X#ifdef CURSES
- X if (iscurses && pageful < screen)
- X move(pageful, 0), clrtobot();
- X#endif /* CURSES */
- X if (cnt == msg_cnt) {
- X while (pageful <= screen) {
- X n_array[pageful-1] = msg_cnt+1; /* assign out-of-range values */
- X#ifdef SUNTOOL
- X if (istool)
- X Clrtoeol(hdr_win, 0, pageful * l_height(DEFAULT), DEFAULT);
- X#endif /* SUNTOOL */
- X ++pageful;
- X }
- X }
- X#ifdef SUNTOOL
- X if (istool) {
- X if (msg_cnt > screen) {
- X panel_set(next_scr, PANEL_SHOW_ITEM, TRUE, 0);
- X panel_set(prev_scr, PANEL_SHOW_ITEM, TRUE, 0);
- X }
- X mail_status(0);
- X }
- X#endif /* SUNTOOL */
- X return 0;
- X}
- X
- X#define NEW 1
- X#define ALL 2
- X
- specl_hdrs(argv, list)
- char **argv, list[];
- X{
- X u_long special = 0;
- X int n = 0;
- X
- X while (argv[0][++n])
- X switch(argv[0][n]) {
- X case 'a': special = ALL;
- X when 'n': special = NEW;
- X when 'u': special = UNREAD;
- X when 'o': special = OLD;
- X when 'd': special = DELETE;
- X when 'r': special = REPLIED;
- X otherwise: print("choose from n,u,o,d,r, or a"); return -1;
- X }
- X if (debug)
- X (void) check_flags(special);
- X
- X for (n = 0; n < msg_cnt; n++) {
- X /*
- X * First, see if we're looking for NEW messages.
- X * If so, then check to see if the msg is unread and not old.
- X * If special > ALL, then special has a mask of bits describing
- X * the state of the message.
- X */
- X if (ison(glob_flags, IS_PIPE)&& !msg_bit(list, n))
- X continue;
- X if (special == ALL || special == NEW &&
- X (ison(msg[n].m_flags, UNREAD) && isoff(msg[n].m_flags, OLD))) {
- X if (isoff(glob_flags, DO_PIPE))
- X print("%s\n", compose_hdr(n));
- X if (list)
- X set_msg_bit(list, n);
- X#ifndef SYSV
- X /*
- X * XENIX compiler can't handle "special" in ison() macro.
- X * It only works if the second argument is a constant!
- X */
- X } else if (special > ALL && ison(msg[n].m_flags, special)) {
- X if (isoff(glob_flags, DO_PIPE))
- X print("%s\n", compose_hdr(n));
- X if (list)
- X set_msg_bit(list, n);
- X#endif /* SYSV */
- X } else {
- X if (list)
- X unset_msg_bit(list, n);
- X if (debug) {
- X printf("msg[%d].m_flags: %d", n, msg[n].m_flags);
- X (void) check_flags(msg[n].m_flags);
- X }
- X }
- X }
- X return 0;
- X}
- X
- X#define Strncpy(buf,p) (void) strncpy(buf,p, sizeof(buf)),buf[sizeof(buf)-1]=0
- X
- X/*
- X * compose a header from the information about a message (from, to, date,
- X * subject, etc..). The header for message number "cnt" is built and is
- X * returned in the static buffer "buf". There will be *at least* 9 chars
- X * in the buffer which will be something like: " 123 >N " The breakdown
- X * is as follows: 4 chars for the message number, 1 space, 1 char for '>'
- X * (if current message) and two spaces for message status (new, unread, etc)
- X * followed by 1 terminating space.
- X * Read other comments in the routine for more info.
- X */
- char *
- compose_hdr(cnt)
- X{
- X static char buf[256];
- X register char *p, *b;
- X char from[256], subject[256], date[17], lines[16], chars[16], line[256];
- X char to[256], addr[256], name[256], status[2];
- X char Day[3], Mon[4], Tm[8], Yr[5], Wkday[4];
- X
- X /* status of the message */
- X if (ison(msg[cnt].m_flags, DELETE))
- X status[0] = '*';
- X else if (ison(msg[cnt].m_flags, OLD) && ison(msg[cnt].m_flags, UNREAD))
- X status[0] = 'U';
- X else if (ison(msg[cnt].m_flags, PRESERVE))
- X status[0] = 'P';
- X else if (isoff(msg[cnt].m_flags, UNREAD))
- X status[0] = ' ';
- X else
- X status[0] = 'N';
- X
- X if (ison(msg[cnt].m_flags, REPLIED))
- X status[1] = 'r';
- X else
- X status[1] = ' ';
- X
- X to[0] = from[0] = subject[0] = date[0] = lines[0] = chars[0] = addr[0] =
- X name[0] = line[0] = Day[0] = Mon[0] = Tm[0] = Yr[0] = Wkday[0] = 0;
- X
- X /* who's the message to */
- X if ((p = header_field(cnt, "to")) ||
- X (p = header_field(cnt, "resent-to")) ||
- X (p = header_field(cnt, "apparently-to")))
- X Strncpy(to, p);
- X
- X /* who the messages is from--
- X * %f From field
- X * %a From address
- X * %n From name
- X */
- X if (!(p = header_field(cnt, "from"))) {
- X /* if all else fails, then get the first token in "From" line */
- X register char *p2;
- X p = ""; /* just in case */
- X if (fseek(tmpf, msg[cnt].m_offset, L_SET) == -1 ||
- X !(p2 = fgets(line, sizeof(line), tmpf))) {
- X error("fseek in %s (msg %d, folder=%s)", tempfile, cnt+1, mailfile);
- X turnon(glob_flags, READ_ONLY);
- X } else if (!(p = index(p2, ' ')))
- X print("Fudged \"From\" line: %s", p2);
- X else if (p2 = any(++p, " \t"))
- X *p2 = 0;
- X }
- X skipspaces(0);
- X (void) no_newln(p);
- X /* if the "from" line produced the user's login name, then the message is
- X * from the user -- attempt to give more useful information by telling
- X * to whom the message was sent. This is not possible if the "to" header
- X * failed to get info (which is probably impossible).
- X */
- X if (!strcmp(p, login) && *to) {
- X (void) strcpy(from, "TO: ");
- X (void) strncpy(from+4, to, sizeof(from)-4), from[sizeof(from)-4] = 0;
- X (void) get_name_n_addr(from+4, name+4, addr+4);
- X if (name[4])
- X (void) strncpy(name,"TO: ",4); /* strncpy doesn't null terminate */
- X if (addr[4])
- X (void) strncpy(addr,"TO: ",4); /* don't overwrite name there */
- X } else {
- X Strncpy(from, p);
- X (void) get_name_n_addr(from, name, addr);
- X }
- X
- X if (p = msg_date(cnt))
- X date_to_string(p, Yr, Mon, Day, Wkday, Tm, date);
- X
- X (void) sprintf(lines, "%d", msg[cnt].m_lines);
- X (void) sprintf(chars, "%ld", msg[cnt].m_size);
- X
- X /* and the subject */
- X if (p = header_field(cnt, "subject"))
- X Strncpy(subject, p);
- X
- X /* now, construct a header out of a format string */
- X if (!hdr_format)
- X hdr_format = DEF_HDR_FMT;
- X
- X (void) sprintf(buf, "%4.d ", cnt+1);
- X b = buf+5;
- X *b++ = ((cnt == current_msg && !iscurses)? '>': ' ');
- X *b++ = status[0], *b++ = status[1];
- X *b++ = ' ';
- X /* use the cnt variable to count chars since beginning of buf
- X * initialize to 9 (strlen(buf) so far). This magic number is
- X * used in other places in msgs.c and mail.c
- X */
- X cnt = 9;
- X for (p = hdr_format; *p; p++)
- X if (*p == '\\')
- X switch (*++p) {
- X case 't':
- X while (cnt % 8)
- X cnt++, *b++ = ' ';
- X when 'n':
- X cnt = 1, *b++ = '\n';
- X otherwise: cnt++, *b++ = *p;
- X }
- X else if (*p == '%') {
- X char fmt[64];
- X register char *p2 = fmt;
- X int len, got_dot = FALSE;
- X
- X *p2++ = '%';
- X if (p[1] != '-')
- X *p2++ = '-';
- X else
- X *++p;
- X while (isdigit(*++p) || !got_dot && *p == '.') {
- X if (*p == '.')
- X got_dot = TRUE;
- X *p2++ = *p;
- X }
- X if (!got_dot && isdigit(p[-1])) {
- X int val;
- X *p2 = 0; /* assure null termination */
- X val = atoi(fmt+1);
- X p2 += strlen(sprintf(p2, ".%d", (val >= 0 ? val : -val)));
- X }
- X *p2++ = 's', *p2 = 0;
- X switch (*p) {
- X case 'f': p2 = from;
- X when 'a':
- X if (!*(p2 = addr))
- X p2 = from;
- X when 'n':
- X if (!*(p2 = name))
- X p2 = from;
- X when '%': p2 = "%";
- X when 't': p2 = to;
- X when 's': p2 = subject;
- X when 'l': p2 = lines;
- X when 'c': p2 = chars;
- X /* date formatting chars */
- X when 'd': p2 = date; /* the full date */
- X when 'T': p2 = Tm;
- X when 'M': p2 = Mon;
- X when 'Y': p2 = Yr;
- X when 'N': p2 = Day;
- X when 'D': p2 = Wkday;
- X otherwise: continue; /* unknown formatting char */
- X }
- X len = strlen(sprintf(b, fmt, p2));
- X cnt += len, b += len;
- X /* Get around a bug in 5.5 IBM RT which pads with NULL's not ' ' */
- X while (cnt && !*(b-1))
- X b--, cnt--;
- X } else
- X cnt++, *b++ = *p;
- X for (*b-- = 0; isspace(*b); --b)
- X *b = 0;
- X return buf;
- X}
- X
- X/*
- X * Using message "n", build a list of recipients that you would mail to if
- X * you were to reply to this message. If "all" is true, then it will take
- X * everyone from the To line in addition to the original sender.
- X * fix_address() is caled from mail.c, not from here. There are too many
- X * other uses for reply_to to always require reconstruction of return paths.
- X * Note that we do NOT deal with Cc paths here either.
- X * Check to make sure that we in fact return a legit address (i.e. not blanks
- X * or null). If such a case occurs, return login name. Always pad end w/blank.
- X */
- char *
- reply_to(n, all, buf)
- register char *buf;
- X{
- X register char *p = NULL, *p2, *b = buf, *field;
- X char line[256];
- X
- X if (field = do_set(set_options, "reply_to_hdr")) {
- X#ifndef MSG_SEPARATOR
- X if (!*field)
- X goto From; /* special case -- get the colon-less From line */
- X#endif /* MSG_SEPARATOR */
- X field = lcase_strcpy(line, field);
- X while (*field) {
- X if (p2 = any(field, " \t,:"))
- X *p2 = 0;
- X if ((p = header_field(n, field)) || !p2)
- X break;
- X else {
- X field = p2+1;
- X while (isspace(*field) || *field == ':' || *field == ',')
- X field++;
- X }
- X }
- X if (!p)
- X print("Warning: message contains no `reply_to_hdr' headers.\n");
- X }
- X if (p || (!p && ((p = header_field(n, "from")) ||
- X (p = header_field(n, "reply-to")) ||
- X (p = header_field(n, "return-path")))))
- X skipspaces(0);
- X else if (!p) {
- X#ifndef MSG_SEPARATOR
- From:
- X /* if all else fails, then get the first token in "From" line */
- X if (fseek(tmpf, msg[n].m_offset, L_SET) == -1 ||
- X !(p2 = fgets(line, sizeof(line), tmpf))) {
- X error("fseek in %s (msg %d, folder=%s)", tempfile, n+1, mailfile);
- X turnon(glob_flags, READ_ONLY);
- X return "";
- X }
- X p = index(p2, ' ');
- X skipspaces(1);
- X if (p2 = index(p, ' '))
- X *p2 = 0;
- X#else /* MSG_SEPARATOR */
- X wprint("Warning: unable to find who msg %d is from!\n", n+1);
- X#endif /* MSG_SEPARATOR */
- X }
- X b += Strcpy(buf, p);
- X
- X /*
- X * if `all' is true, append everyone on the "To:" line.
- X * cc_to(), called separately, will catch the cc's
- X */
- X if (all && (p = header_field(n, "to")) && *p) {
- X b += Strcpy(b, ", ");
- X /* The assumption that BUFSIZ is correct is unwise, but I know it
- X * to be true for Mush. Be forewarned if you call this routine.
- X */
- X (void) strncpy(b, p, BUFSIZ - (b - buf) - 2);
- X buf[BUFSIZ-3] = 0;
- X }
- X fix_up_addr(buf);
- X take_me_off(buf);
- X for (p = buf; *p == ',' || isspace(*p); p++);
- X if (!*p)
- X (void) strcpy(buf, login);
- X return strcat(buf, " ");
- X}
- X
- char *
- subject_to(n, buf)
- register char *buf;
- X{
- X register char *p;
- X buf[0] = 0; /* make sure it's already null terminated */
- X if (!(p = header_field(n, "subject")))
- X return NULL;
- X if (strncmp(p, "Re:", 3))
- X (void) strcpy(buf, "Re: ");
- X return strcat(buf, p);
- X}
- X
- char *
- cc_to(n, buf)
- register char *buf;
- X{
- X register char *p;
- X buf[0] = 0; /* make sure it's already null terminated */
- X if (!(p = header_field(n, "cc")))
- X return NULL;
- X fix_up_addr(buf);
- X take_me_off(p);
- X return strcpy(buf, p);
- X}
- X
- X/*
- X * fix addresses according to the sender's address. If he's on a remote
- X * machine, chances are that the addresses of everyone else he mailed to
- X * are addresses from his machine. Reconstruct those addresses to route
- X * thru the senders machine first.
- X */
- fix_addresses(to, cc)
- char *to, *cc;
- X{
- X char pre_path[256], addr[256], name[256], buf[BUFSIZ], c, *p2;
- X register char *next, *p, *b = buf, *str;
- X int pre_len = 0;
- X
- X pre_path[0] = 0;
- X /* Get the address of the sender (which is always listed first) */
- X if (!(next = get_name_n_addr(to, name, addr)))
- X return;
- X
- X /* fix up the sender's address; improve_uucp_path to optimize pre_path */
- X improve_uucp_paths(addr);
- X
- X /* if user didn't route via uucp, pre_path will be blank */
- X if (p = rindex(addr, '!')) {
- X c = *++p, *p = 0;
- X (void) strcpy(pre_path, addr); /* the uucp route he used */
- X pre_len = strlen(pre_path);
- X *p = c;
- X Debug("Routing thru \"%s\"\n", pre_path);
- X }
- X
- X b += Strcpy(b, addr);
- X if (*name)
- X b += strlen(sprintf(b, " (%s)", name));
- X while (*next == ',' || isspace(*next)) /* move next to the next address */
- X next++;
- X if (*next) /* there's more to come on the To line */
- X b += Strcpy(b, ", ");
- X else {
- X (void) strcpy(to, buf);
- X if (!cc || !*cc)
- X return;
- X }
- X for (str = next, c = 0; c < 2; str = cc, c++) {
- X if (str == cc)
- X b = buf;
- X *b = 0; /* null terminate beginning in case there's nothing to do */
- X if (!str || !*str)
- X continue;
- X do {
- X /* get_name returns a pointer to the next address */
- X if (!(p = get_name_n_addr(str, name, addr)))
- X break;
- X /* check to see if there's enough buffer space to add this addr */
- X if ((b - buf) + pre_len + strlen(addr) + strlen(name) + 5 >= BUFSIZ)
- X break;
- X while (p2 = index(addr, '@'))
- X *p2++ = '%'; /* '@' has too high precedence for uucp paths */
- X /* don't prepend the sender's path unless required */
- X if (pre_len && strncmp(addr, pre_path, pre_len))
- X b += Strcpy(b, pre_path);
- X b += Strcpy(b, addr);
- X if (*name)
- X b += strlen(sprintf(b, " (%s)", name));
- X while (*p == ',' || isspace(*p))
- X p++;
- X if (*p)
- X b += Strcpy(b, ", ");
- X } while (*(str = p));
- X for (b--; b > buf && (*b == ',' || isspace(*b)); b--)
- X *b = 0;
- X improve_uucp_paths(buf);
- X if (c == 0)
- X (void) strcpy(to, buf);
- X else
- X (void) strcpy(cc, buf);
- X }
- X}
- X
- X/*
- X * pass a string describing header like, "Subject: ", current value, and
- X * whether or not to prompt for it or to just post the information.
- X * If do_prompt is true, "type in" the current value so user can either
- X * modify it, erase it, or add to it.
- X */
- char *
- set_header(str, curstr, do_prompt)
- register char *str, *curstr;
- X{
- X static char buf[BUFSIZ];
- X int offset = 0;
- X register char *p = curstr;
- X
- X buf[0] = 0;
- X wprint(str);
- X fflush(stdout); /* force str curstr */
- X if (do_prompt) {
- X if (curstr)
- X for (p = curstr; *p; p++)
- X#ifdef SUNTOOL
- X if (istool)
- X rite(*p); /* mimics typing for the tool */
- X else
- X#endif /* SUNTOOL */
- X if (isoff(glob_flags, ECHO_FLAG))
- X fputc((buf[offset++] = *p), stdout);
- X else
- X#ifdef TIOCSTI
- X if (ioctl(0, TIOCSTI, p) == -1) {
- X error("ioctl: TIOCSTI");
- X wprint("You must retype the entire line.\n%s", str);
- X break;
- X }
- X#else
- X {
- X wprint("WARNING: -e flag! Type the line over.\n%s", str);
- X break;
- X }
- X#endif /* TIOCSTI */
- X
- X if (istool)
- X return NULL;
- X /* simulate the fact that we're getting input for the letter even tho
- X * we may not be. set_header is called before IS_GETTING is true,
- X * but if we set it to true temporarily, then signals will return to
- X * the right place (stop/continue).
- X */
- X {
- X u_long getting = ison(glob_flags, IS_GETTING);
- X if (!getting)
- X turnon(glob_flags, IS_GETTING);
- X if (Getstr(buf, sizeof(buf), offset) == -1)
- X buf[0] = 0;
- X if (!getting)
- X turnoff(glob_flags, IS_GETTING);
- X }
- X } else
- X puts(strcpy(buf, curstr));
- X if (debug > 1)
- X print("returning (%s) from set_header\n", buf);
- X return buf;
- X}
- X
- X/*
- X * improve uucp paths by looking at the name of each host listed in the
- X * path given.
- X * sun!island!pixar!island!argv
- X * It's a legal address, but redundant. Also, if we know we talk to particular
- X * hosts via uucp, then we can just start with that host and disregard the path
- X * preceding it. So, first get the known hosts and save them. Then start
- X * at the end of the original path (at the last ! found), and move backwards
- X * saving each hostname. If we get to a host that we know about, stop there
- X * and use that address. If we get to a host we've already seen, then
- X * delete it and all the hosts since then until the first occurance of that
- X * hostname. When we get to the beginning, the address will be complete.
- X *
- X * Return all results into the original buffer passed to us. Since we can
- X * at worst not touch the path (shorten it if anything), we know we're not
- X * going to overrun the buffer.
- X */
- improve_uucp_paths(original)
- register char *original;
- X{
- X char *hostnames[128];
- X char name[BUFSIZ], addr[BUFSIZ], buf[BUFSIZ], *knowns, *end;
- X register char *p, *recipient, *start = original, *b = buf;
- X int saved_hosts, i;
- X
- X if (!original || !*original)
- X return;
- X
- X knowns = do_set(set_options, "known_hosts");
- X
- X while (end = get_name_n_addr(start, name, addr)) {
- X saved_hosts = 0;
- X /* no uucp path, just user name [@host] with optional name attached */
- X if (!(p = rindex(addr, '!'))) {
- X char c = *end;
- X *end = 0;
- X b += Strcpy(b, start); /* copy the entire address with comments */
- X *end = c;
- X recipient = NULL;
- X } else {
- X recipient = p+1;
- X while (p > addr) {
- X /* null the '!' separating the rest of the path from the part
- X * of the path preceding it and move p back to the previous
- X * '!' (or beginning to addr) for hostname to point to.
- X */
- X for (*p-- = 0; p > addr && *p != '!'; p--)
- X ;
- X /* if p is not at the addr, move it forward past the '!' */
- X if (p != addr)
- X ++p; /* now points to a null terminated hostname */
- X#ifndef SYSV
- X /* if host is ourselves, ignore this and preceding hosts */
- X for (i = 0; i < MAX_HOST_NAMES && ourname[i]; i++)
- X if (!lcase_strcmp(p, ourname[i]))
- X break;
- X if (i < MAX_HOST_NAMES && ourname[i])
- X break; /* our own host is not included in the path */
- X#endif /* SYSV */
- X /* check already saved hostnames. If host is one of them,
- X * delete remaining hostnames since there is a redundant path.
- X */
- X for (i = 0; i < saved_hosts; i++)
- X if (!lcase_strcmp(hostnames[i], p))
- X saved_hosts = i;
- X
- X hostnames[saved_hosts++] = p;
- X /* If we know that we call this host, break */
- X if (p == addr || knowns && chk_two_lists(p, knowns, " ,\t"))
- X break;
- X --p; /* move p back onto the '!'; it will not equal addr */
- X }
- X while (saved_hosts-- > 0) {
- X b += Strcpy(b, hostnames[saved_hosts]);
- X *b++ = '!';
- X }
- X if (recipient)
- X b += Strcpy(b, recipient);
- X if (*name)
- X b += strlen(sprintf(b, " (%s)", name));
- X }
- X for (start = end; *start == ',' || isspace(*start); start++)
- X ;
- X if (!*start)
- X break;
- X b += Strcpy(b, ", ");
- X }
- X (void) strcpy(original, buf);
- X}
- X
- X/*
- X * rm_cmts_in_addr() removes the comment lines in addresses that result from
- X * sendmail or other mailers which append the user's "real name" on the
- X * from lines. See get_name_n_addr().
- X */
- rm_cmts_in_addr(str)
- register char *str;
- X{
- X char addr[BUFSIZ], buf[BUFSIZ], *start = str;
- X register char *b = buf;
- X
- X *b = 0;
- X do {
- X if (!(str = get_name_n_addr(str, NULL, addr)))
- X break;
- X b += Strcpy(b, addr);
- X while (*str == ',' || isspace(*str))
- X str++;
- X if (*str)
- X b += Strcpy(b, ", ");
- X } while (*str);
- X for (b--; b > start && (*b == ',' || isspace(*b)); b--)
- X *b = 0;
- X (void) strcpy(start, buf);
- X}
- X
- X/*
- X * take_me_off() is intended to search for the user's login name in an
- X * address string and remove it. Note that string should be legal addresses
- X * only -- no (comments) allowed here. See rm_cmts_in_addr().
- X * If "metoo" is set, don't touch addr. This implementation is very bug prone
- X * because the user's name may be a hostname or the path specified may
- X * be incomplete.
- X */
- take_me_off(str)
- char *str;
- X{
- X int i = 0, rm_me;
- X char addr[BUFSIZ], buf[BUFSIZ], *start = str;
- X char *Alts;
- X register char *p, *b = buf;
- X
- X if (!str || !*str || do_set(set_options, "metoo"))
- X return;
- X
- X Alts = do_set(set_options, "alternates");
- X
- X *b = 0;
- X do {
- X if (!(p = get_name_n_addr(str, NULL, addr)))
- X break;
- X rm_me = FALSE;
- X /* see if user's login is in the address */
- X if (!strcmp(login, addr))
- X rm_me = TRUE;
- X /* if Alts is not set and the above strcmp failed, don't remove him */
- X else if (*addr && Alts && *Alts && chk_two_lists(login,addr, "!@%=")) {
- X /* To be in this block, there must be a remote address */
- X i = 0; /* initialize 'i' in case while loop is skipped */
- X#ifndef SYSV
- X /* see if the hostnames match our hostname. */
- X while (i < MAX_HOST_NAMES && ourname[i])
- X if (chk_two_lists(addr, ourname[i++], "!@%="))
- X break;
- X#endif /* SYSV */
- X /* If one of the hostnames in the address is one of user's
- X * hostnames, remove this address. If the alternates
- X * hostnames listed contains a hostname in the address, remove
- X * from the list.
- X */
- X if (
- X#ifndef SYSV
- X i < MAX_HOST_NAMES && ourname[i] ||
- X#endif /* SYSV */
- X *Alts == '*' || !chk_two_lists(addr, Alts, "!@%= \t,"))
- X rm_me = TRUE;
- X }
- X if (!rm_me) {
- X char c = *p;
- X *p = 0;
- X b += Strcpy(b, str);
- X *p = c;
- X }
- X while (*p == ',' || isspace(*p))
- X p++;
- X if (*p && !rm_me)
- X b += Strcpy(b, ", ");
- X } while (*(str = p));
- X for (b--; b > start && (*b == ',' || isspace(*b)); b--)
- X *b = 0;
- X (void) strcpy(start, buf);
- X}
- X
- X/*
- X * Place commas in between all addresses that don't already have
- X * them. Addresses which use comments which are in parens or _not_
- X * within angle brackets *must* already have commas around them or
- X * you can't determine what is a comment and what is an address.
- X */
- fix_up_addr(str)
- register char *str;
- X{
- X char buf[BUFSIZ], *start = str, c;
- X register char *p, *b = buf;
- X
- X *b = 0;
- X do {
- X /* get_name returns a pointer to the next address */
- X if (!(p = get_name_n_addr(str, NULL, NULL)))
- X break;
- X c = *p, *p = 0;
- X if (strlen(str) + (b - buf) >= BUFSIZ - 2) {
- X /* print("Address too long! Lost address: \"%s\"\n", str); */
- X *p = c;
- X break;
- X }
- X for (b += Strcpy(b, str); b > buf && isspace(*(b-1)); b--)
- X *b = 0;
- X for (*p = c; *p == ',' || isspace(*p); p++)
- X ;
- X if (*p)
- X b += Strcpy(b, ", ");
- X } while (*(str = p));
- X for (b--; b > buf && (*b == ',' || isspace(*b)); b--)
- X *b = 0;
- X (void) strcpy(start, buf);
- X}
- X
- X/*
- X * Get address and name from a string (str) which came from an address header
- X * in a message or typed by the user. The string may contain one or more
- X * well-formed addresses. Each must be separated by a comma.
- X *
- X * address, address, address
- X * address (comment or name here)
- X * comment or name <address>
- X * "Comment, even those with comma's!" <address>
- X * address (comma, (more parens), etc...)
- X *
- X * This does *not* handle cases like:
- X * comment <address (comment)>
- X *
- X * find the *first* address here and return a pointer to the end of the
- X * address (usually a comma). Return NULL on error: non-matching parens,
- X * brackets, quotes...
- X */
- char *
- get_name_n_addr(str, name, addr)
- register char *str, *name, *addr;
- X{
- X register char *p, *p2, *beg_addr = addr, *beg_name = name, c;
- X
- X if (addr)
- X *addr = 0;
- X if (name)
- X *name = 0;
- X if (!str || !*str)
- X return NULL;
- X
- X /* first check to see if there's something to look for */
- X if (!(p = any(str, ",(<\""))) {
- X /* no comma or indication of a quote character. Find a space and
- X * return that. If nothing, the entire string is a complete address
- X */
- X if (p = any(str, " \t"))
- X c = *p, *p = 0;
- X if (addr)
- X (void) strcpy(addr, str);
- X if (p)
- X *p = c;
- X return p? p : str + strlen(str);
- X }
- X
- X /* comma terminated before any comment stuff. If so, check for whitespace
- X * before-hand cuz it's possible that strings aren't comma separated yet
- X * and they need to be.
- X *
- X * address address address, address
- X * ^p <- p points here.
- X * ^p2 <- should point here.
- X */
- X if (*p == ',') {
- X c = *p, *p = 0;
- X if (p2 = any(str, " \t"))
- X *p = ',', c = *p2, p = p2;
- X if (addr)
- X (void) strcpy(addr, str);
- X *p = c;
- X return p;
- X }
- X
- X /* starting to get hairy -- we found an angle bracket. This means that
- X * everything outside of those brackets are comments until we find that
- X * all important comma. A comment AFTER the <addr> :
- X * <address> John Doe
- X * can't call this function recursively or it'll think that "John Doe"
- X * is a string with two legal address on it (each name being an address).
- X */
- X if (*p == '<') { /* note that "str" stil points to comment stuff! */
- X if (name && *str) {
- X *p = 0;
- X name += Strcpy(name, str);
- X *p = '<';
- X }
- X if (!(p2 = index(p+1, '>'))) {
- X wprint("Warning! Malformed address: \"%s\"\n", str);
- X return NULL;
- X }
- X if (addr) {
- X /* to support <addr (comment)> style addresses, add code here */
- X *p2 = 0;
- X skipspaces(1);
- X addr += Strcpy(addr, p);
- X while (addr > beg_addr && isspace(*(addr-1)))
- X *--addr = 0;
- X *p2 = '>';
- X }
- X /* take care of the case "... <addr> com (ment)" */
- X {
- X int p_cnt = 0; /* parenthesis counter */
- X p = p2;
- X /* don't recurse yet -- scan till null, comma or '<'(add to name) */
- X for (p = p2; p[1] && (p_cnt || p[1] != ',' && p[1] != '<'); p++) {
- X if (p[1] == '(')
- X p_cnt++;
- X else if (p[1] == ')')
- X p_cnt--;
- X if (name)
- X *name++ = p[1];
- X }
- X if (p_cnt) {
- X wprint("Warning! Malformed name: \"%s\"\n", name);
- X return NULL;
- X }
- X }
- X if (name && name > beg_name) {
- X while (isspace(*(name-1)))
- X --name;
- X *name = 0;
- X }
- X }
- X
- X /* this is the worst -- now we have parentheses/quotes. These guys can
- X * recurse pretty badly and contain commas within them.
- X */
- X if (*p == '(' || *p == '"') {
- X char *start = p;
- X int comment = 1;
- X c = *p;
- X /* "str" points to address while p points to comments */
- X if (addr && *str) {
- X *p = 0;
- X while (isspace(*str))
- X str++;
- X addr += Strcpy(addr, str);
- X while (addr > beg_addr && isspace(*(addr-1)))
- X *--addr = 0;
- X *p = c;
- X }
- X while (comment) {
- X if (c == '"' && !(p = index(p+1, '"')) ||
- X c == '(' && !(p = any(p+1, "()"))) {
- X wprint("Warning! Malformed address: \"%s\"\n", str);
- X return NULL;
- X }
- X if (*p == '(') /* loop again on parenthesis. quote ends loop */
- X comment++;
- X else
- X comment--;
- X }
- X /* Something like ``Comment (Comment) <addr>''. In this case
- X * the name should include both comment parts with the
- X * parenthesis. We have to redo addr.
- X */
- X if ((p2 = any(p+1, "<,")) && *p2 == '<') {
- X if (!(p = index(p2, '>'))) {
- X wprint("Warning! Malformed address: \"%s\"\n", str);
- X return NULL;
- X }
- X if (addr = beg_addr) { /* reassign addr and compare to null */
- X c = *p; *p = 0;
- X addr += Strcpy(addr, p2+1);
- X while (addr > beg_addr && isspace(*(addr-1)))
- X *--addr = 0;
- X *p = c;
- X }
- X if (name) {
- X c = *p2; *p2 = 0;
- X name += Strcpy(name, str);
- X while (name > beg_name && isspace(*(name-1)))
- X *--name = 0;
- X *p2 = c;
- X }
- X } else if (name && start[1]) {
- X c = *p, *p = 0; /* c may be ')' instead of '(' now */
- X name += Strcpy(name, start+1);
- X while (name > beg_name && isspace(*(name-1)))
- X *--name = 0;
- X *p = c;
- X }
- X }
- X skipspaces(1);
- X /* this is so common, save time by returning now */
- X if (!*p || *p == ',')
- X return p;
- X return get_name_n_addr(p, name, addr);
- X}
- END_OF_FILE
- if test 30675 -ne `wc -c <'hdrs.c'`; then
- echo shar: \"'hdrs.c'\" unpacked with wrong size!
- fi
- # end of 'hdrs.c'
- fi
- echo shar: End of archive 10 \(of 14\).
- cp /dev/null ark10isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 14 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-